#include "stdafx.h"
#include "JSocket.h"


JSocket::JSocket()
{
	m_hSocket = INVALID_SOCKET; //default to an invalid socket descriptor
}


JSocket::~JSocket()
{
	Close();
}

void JSocket::Attach(SOCKET s)
{
	ASSERT(s != INVALID_SOCKET);
	m_hSocket = s;
}

SOCKET JSocket::Detach()
{
	SOCKET s = m_hSocket;
	m_hSocket = INVALID_SOCKET;
	return s;
}

BOOL JSocket::GetPeerName(struct sockaddr * lpSockAddr, int * lpSockAddrLen)
{
	if (!getpeername(m_hSocket, (struct sockaddr *)lpSockAddr, lpSockAddrLen))
		return TRUE;
	return FALSE;
}

BOOL JSocket::GetPeerName(CString & rPeerAddress, UINT & rPeerPort)
{
	struct sockaddr_in sa;
	int len = sizeof(sa);
	if (!getpeername(m_hSocket, (struct sockaddr *)&sa, &len))
	{
		rPeerAddress.Format(_T("%d.%d.%d.%d"), sa.sin_addr.S_un.S_un_b.s_b1, sa.sin_addr.S_un.S_un_b.s_b2,
			sa.sin_addr.S_un.S_un_b.s_b3, sa.sin_addr.S_un.S_un_b.s_b4);
		rPeerPort = sa.sin_port;
		return TRUE;
	}
	return FALSE;
}

int JSocket::Send(LPCSTR pszBuf, int nBuf)
{
	ASSERT(m_hSocket != INVALID_SOCKET);
	if (m_hSocket == INVALID_SOCKET) return -1;
	return ::send(m_hSocket, pszBuf, nBuf, 0);
}

int JSocket::Receive(LPSTR pszBuf, int nBuf)
{
	ASSERT(m_hSocket != INVALID_SOCKET);

	return ::recv(m_hSocket, pszBuf, nBuf, 0);
}

void JSocket::Close()
{
	if (m_hSocket != INVALID_SOCKET)
	{
		OnClose(0);
		VERIFY(SOCKET_ERROR != ::closesocket(m_hSocket));
		m_hSocket = INVALID_SOCKET;
	}
}

BOOL JSocket::IsReadible(BOOL & bReadible, DWORD dwTimeout)
{
	if (m_hSocket == INVALID_SOCKET) return FALSE;

	timeval timeout;
	timeout.tv_sec = dwTimeout / 1000;
	timeout.tv_usec = dwTimeout % 1000;
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(m_hSocket, &fds);
	int nStatus = ::select(0, &fds, NULL, NULL, &timeout);
	if (nStatus == SOCKET_ERROR)
		return FALSE;
	else
	{
		bReadible = !(nStatus == 0);
		return TRUE;
	}
}

BOOL JSocket::Create()
{
	m_hSocket = ::socket(AF_INET, SOCK_STREAM, 0);
	return (m_hSocket != INVALID_SOCKET);
}

BOOL JSocket::Bind(const sockaddr_in * lpSocketAddress)
{
	ASSERT(m_hSocket != INVALID_SOCKET);

	return (::bind(m_hSocket, (const sockaddr*)lpSocketAddress, sizeof(sockaddr_in)) != SOCKET_ERROR);
}

BOOL JSocket::Bind(unsigned short uPort)
{
	sockaddr_in socketAddress;
	socketAddress.sin_family = AF_INET;
	socketAddress.sin_port = htons((u_short)uPort);
	socketAddress.sin_addr.s_addr = htonl(INADDR_ANY); //Bind to any IP address
	return Bind(&socketAddress);
}

BOOL JSocket::Listen()
{
	ASSERT(m_hSocket != INVALID_SOCKET);

	return (::listen(m_hSocket, SOMAXCONN) != SOCKET_ERROR);
}

BOOL JSocket::Accept(JSocket & clientSocket)
{
	ASSERT(m_hSocket != INVALID_SOCKET);

	struct sockaddr_in clientAddress;
	int nSize = sizeof(sockaddr_in);
	SOCKET hSocket = ::accept(m_hSocket, (sockaddr*)&clientAddress, &nSize);
	if (hSocket == INVALID_SOCKET) return FALSE;

	clientSocket.Attach(hSocket);
	return TRUE;
}

BOOL JSocket::Accept(SOCKET & clientSocket, sockaddr_in & clientAddress)
{
	ASSERT(m_hSocket != INVALID_SOCKET);

	int nSize = sizeof(sockaddr_in);
	clientSocket = ::accept(m_hSocket, (sockaddr*)&clientAddress, &nSize);

	return (clientSocket != INVALID_SOCKET);
}

BOOL JSocket::Connect(char * domain, UINT uPort)
{
	u_long	uAddr = 0;
	HOSTENT * host = gethostbyname(domain);
	struct sockaddr_in in;
	int i = 0;
	while (host && host->h_addr_list[i])
	{
		memcpy(&in.sin_addr.s_addr, host->h_addr_list[i], host->h_length);
		char * ip = inet_ntoa(in.sin_addr);
		if (ip)
		{
			uAddr = inet_addr(ip);
			break;
		}
		i++;
	}
	if (uAddr == 0) return FALSE;

	struct sockaddr_in from;
	from.sin_addr.S_un.S_addr = uAddr;
	from.sin_family = AF_INET;
	from.sin_port = htons(uPort);

	if ((connect(m_hSocket, (struct sockaddr *)&from, sizeof(struct sockaddr))) == -1)
	{
		return FALSE;
	}

	return TRUE;
}

void JSocket::OnClose(int nErrorCode)
{
}